home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / DOMSUBR.C < prev    next >
Text File  |  1993-10-14  |  38KB  |  1,591 lines

  1. #include <ctype.h>
  2.  
  3. #include "global.h"
  4. #include "config.h"
  5. #include "mbuf.h"
  6. #include "domain.h"
  7. #include "netuser.h"
  8. #include "socket.h"
  9. #include "files.h"
  10.  
  11. static struct rr *Rrlist[NRLIST];
  12.  
  13. #ifdef ENH
  14. struct dlist *Lorigin = NULLDLIST;
  15. struct rr *Rrlistl[NRLIST];
  16. char *Dorigin = NULLCHAR;
  17. #else
  18. static struct dlist *Lorigin = NULLDLIST;
  19. static struct rr *Rrlistl[NRLIST];
  20. static char *Dorigin = NULLCHAR;
  21. #endif
  22.  
  23. /*
  24. static int near
  25. strxlen(char *s)
  26. {
  27.     int i = 0;
  28.  
  29.     while(*s++ != '\0')
  30.         i++;
  31.     return i;
  32. }
  33. */
  34.  
  35. int
  36. sendquery(int32 address,char *buf,int len,struct mbuf **bp,int32 timeout)
  37. {
  38.     int s, resp = -1;
  39.  
  40.     if((s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
  41.         struct sockaddr_in server;
  42.  
  43.         *bp = qdata(buf,len);
  44.         xfree(buf);
  45.         server.sin_family = AF_INET;
  46.         server.sin_port = IPPORT_DOMAIN;
  47.         server.sin_addr.s_addr = address;
  48.         send_mbuf(s,*bp,0,(char *)&server,SOCKSIZE);
  49.  
  50.         if(timeout) {                   /* Wait for something to happen */
  51.             alarm(timeout);
  52.             resp = recv_mbuf(s,bp,0,NULLCHAR,0);
  53.             alarm(0L);
  54.         }
  55.         close_s(s);
  56.     }
  57.     return resp;
  58. }
  59.  
  60. static char * near
  61. dn_compress(char *cp,char *name)
  62. {
  63.     int dlen = strlen(name);
  64.  
  65.     for(;;){
  66.         /* Look for next dot */
  67.         char *cp1 = strchr(name,'.');
  68.         int len = (cp1 != NULLCHAR) ? (int)(cp1 - name) : dlen;
  69.  
  70.         *cp++ = len;        /* Write length of component */
  71.  
  72.         if(len == 0) {
  73.             return cp;
  74.         }
  75.         /* Copy component up to (but not including) dot */
  76.         strncpy(cp,name,len);
  77.         cp += len;
  78.  
  79.         if(cp1 == NULLCHAR) {
  80.             *cp++ = 0;    /* Last one; write null and finish */
  81.             return cp;
  82.         }
  83.         name += len+1;
  84.         dlen -= len+1;
  85.     }
  86. }
  87.  
  88. /* Convert a compressed domain name to the human-readable form */
  89. static int near
  90. dn_expand(
  91. char *msg,                    /* Complete domain message */
  92. char *eom,
  93. char *compressed,            /* Pointer to compressed name */
  94. char *full,                    /* Pointer to result buffer */
  95. int fullen)                    /* Length of same */
  96. {
  97.     int clen = 0;            /* Total length of compressed name */
  98.     int indirect = 0;        /* Set if indirection encountered */
  99.     int nseg = 0;            /* Total number of segments in name */
  100.     char *cp = compressed;
  101.  
  102.     for(;;){
  103.         unsigned int slen = uchar(*cp++);    /* Length of this segment */
  104.  
  105.         if(!indirect) {
  106.             clen++;
  107.         }
  108.         if((slen & 0xc0) == 0xc0) {
  109.             if(!indirect) {
  110.                 clen++;
  111.             }
  112.             indirect = 1;
  113.  
  114.             /* Follow indirection */
  115.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  116.             slen = uchar(*cp++);
  117.         }
  118.         if(slen == 0) {                        /* zero length == all done */
  119.             break;
  120.         }
  121.         if((fullen -= slen + 1) < 0) {
  122.             return -1;
  123.         }
  124.         if(!indirect) {
  125.             clen += slen;
  126.         }
  127.         while(slen-- != 0) {
  128.             *full++ = *cp++;
  129.         }
  130.         *full++ = '.';
  131.         nseg++;
  132.     }
  133.     if(nseg == 0) {
  134.         /* Root name; represent as single dot */
  135.         *full++ = '.';
  136.         fullen--;
  137.     }
  138.     *full++ = '\0';
  139.     fullen--;
  140.     return clen;                            /* Length of compressed message */
  141. }
  142.  
  143. static char * near
  144. getq(struct quest *qp,char *msg,char *cp)
  145. {
  146.     int len;
  147.     char name[512];
  148.  
  149.     if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  150.         return NULLCHAR;
  151.     }
  152.     cp += len;
  153.     qp->qname = strxdup(name);
  154.     qp->qtype = get16(cp);
  155.     cp += 2;
  156.     qp->qclass = get16(cp);
  157.     cp += 2;
  158.     return cp;
  159. }
  160.  
  161. /* Read a resource record from a domain message into a host structure */
  162. static char * near
  163. ntohrr(
  164. struct rr *rrp,        /* Pointer to allocated resource record structure */
  165. char *msg,            /* Pointer to beginning of domain message */
  166. char *cp)            /* Pointer to start of encoded RR record */
  167. {
  168.     int len;
  169.     char name[512];
  170.  
  171.     if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  172.         return NULLCHAR;
  173.     }
  174.     cp += len;
  175.     rrp->name = strxdup(name);
  176.     rrp->type = get16(cp);
  177.     cp += 2;
  178.     rrp->class = get16(cp);
  179.     cp+= 2;
  180.     rrp->ttl = get32(cp);
  181.     cp += 4;
  182.     rrp->rdlength = get16(cp);
  183.     cp += 2;
  184.  
  185.     switch(rrp->type){
  186.     case TYPE_CNAME:
  187.     case TYPE_MB:
  188.     case TYPE_MG:
  189.     case TYPE_MR:
  190.     case TYPE_NS:
  191.     case TYPE_PTR:
  192.         /* These types all consist of a single domain name;
  193.          * convert it to ascii format
  194.          */
  195.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  196.             return NULLCHAR;
  197.         }
  198.         rrp->rdata.name = strxdup(name);
  199.         cp += len;
  200.         break;
  201.     case TYPE_A:
  202.         /* Just read the address directly into the structure */
  203.         rrp->rdata.addr = get32(cp);
  204.         cp += 4;
  205.         break;
  206.     case TYPE_HINFO:
  207.         rrp->rdata.hinfo.cpu = mxallocw(*cp + 1);
  208.         strncpy(rrp->rdata.hinfo.cpu,cp+1,*cp);
  209.         cp += *cp + 1;
  210.         rrp->rdata.hinfo.os = mxallocw(*cp + 1);
  211.         strncpy(rrp->rdata.hinfo.os,cp+1,*cp);
  212.         cp += *cp + 1;
  213.         break;
  214.     case TYPE_MX:
  215.         rrp->rdata.mx.pref = get16(cp);
  216.         cp += 2;
  217.  
  218.         /* Get domain name of exchanger */
  219.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  220.             xfree(rrp->name);
  221.             return NULLCHAR;
  222.         }
  223.         rrp->rdata.mx.exch = strxdup(name);
  224.         cp += len;
  225.         break;
  226.     case TYPE_SOA:
  227.         /* Get domain name of name server */
  228.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  229.             xfree(rrp->name);
  230.             return NULLCHAR;
  231.         }
  232.         rrp->rdata.soa = mxallocw(sizeof(struct soa));
  233.         rrp->rdata.soa->mname = strxdup(name);
  234.         cp += len;
  235.  
  236.         /* Get domain name of responsible person */
  237.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  238.             xfree(rrp->rdata.soa->mname);
  239.             xfree(rrp->rdata.soa);
  240.             xfree(rrp->name);
  241.             return NULLCHAR;
  242.         }
  243.         rrp->rdata.soa->rname = strxdup(name);
  244.         cp += len;
  245.  
  246.         rrp->rdata.soa->serial = get32(cp);
  247.         cp += 4;
  248.         rrp->rdata.soa->refresh = get32(cp);
  249.         cp += 4;
  250.         rrp->rdata.soa->retry = get32(cp);
  251.         cp += 4;
  252.         rrp->rdata.soa->expire = get32(cp);
  253.         cp += 4;
  254.         rrp->rdata.soa->minimum = get32(cp);
  255.         cp += 4;
  256.         break;
  257.     case TYPE_TXT:
  258.         /* Just stash */
  259.         rrp->rdata.data = mxallocw(rrp->rdlength);
  260.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  261.         cp += rrp->rdlength;
  262.         break;
  263.     case TYPE_MD:    /* Not supported */
  264.     case TYPE_MF:    /* Not supported */
  265.     case TYPE_NULL: /* Not supported */
  266.     case TYPE_WKS:    /* Not supported */
  267.     case TYPE_MINFO:    /* Not supported */
  268.         if((len = dn_expand(msg,NULLCHAR,cp,name,sizeof(name))) == -1) {
  269.             xfree(rrp->name);
  270.             return NULLCHAR;
  271.         }
  272.         rrp->rdata.name = strxdup(name);
  273.         cp += len;
  274.         break;
  275.     default:
  276.         /* Ignore */
  277.         cp += rrp->rdlength;
  278.         break;
  279.     }
  280.     return cp;
  281. }
  282.  
  283. static char * near
  284. htonrr(struct rr *rr,char *buffer)
  285. {
  286.     struct rr *rrp;
  287.     char *cp = buffer;
  288.  
  289.     for(rrp = rr; rrp != NULLRR; rrp = rrp->next) {
  290.         int i = strlen(rrp->name), len;
  291.  
  292.         if(rrp->name[i-1] != '.' && rrp->origin != NULLCHAR) {
  293.             char *p = mxallocw(i + strlen(rrp->origin) + 2);
  294.             sprintf(p,"%s.%s",rrp->name,rrp->origin);
  295.             cp = dn_compress(cp,p);
  296.             xfree(p);
  297.         } else {
  298.             cp = dn_compress(cp,rrp->name);
  299.         }
  300.         cp = put16(cp,rrp->type);
  301.         cp = put16(cp,rrp->class);
  302.         cp = put32(cp,3600L);        /* time to live */
  303.         cp = put16(cp,rrp->rdlength);
  304.  
  305.         switch(rrp->type) {
  306.         case TYPE_A:
  307.             cp = put32(cp,rrp->rdata.addr);
  308.             break;
  309.         case TYPE_SOA:
  310.             cp = dn_compress(cp,rrp->rdata.soa->mname);
  311.             cp = dn_compress(cp,rrp->rdata.soa->rname);
  312.             cp = put32(cp,rrp->rdata.soa->serial);
  313.             cp = put32(cp,rrp->rdata.soa->refresh);
  314.             cp = put32(cp,rrp->rdata.soa->retry);
  315.             cp = put32(cp,rrp->rdata.soa->expire);
  316.             cp = put32(cp,rrp->rdata.soa->minimum);
  317.             break;
  318.         case TYPE_HINFO:
  319.             *cp++ = len = strlen(rrp->rdata.hinfo.cpu);
  320.             strncpy(cp,rrp->rdata.hinfo.cpu,len);
  321.             cp += len;
  322.             *cp++ = len = strlen(rrp->rdata.hinfo.os);
  323.             strncpy(cp,rrp->rdata.hinfo.os,len);
  324.             cp += len;
  325.             break;
  326.         case TYPE_MX:
  327.             cp = put16(cp,rrp->rdata.mx.pref);
  328.             cp = dn_compress(cp,rrp->rdata.mx.exch);
  329.             break;
  330.         case TYPE_CNAME:
  331.         case TYPE_MB:
  332.         case TYPE_MG:
  333.         case TYPE_MR:
  334.         case TYPE_NS:
  335.         case TYPE_PTR:
  336.             cp = dn_compress(cp,rrp->rdata.data);
  337.             break;
  338.         case TYPE_MINFO:    /* Unsupported type */
  339.             cp = dn_compress(cp,rrp->rdata.minfo.rmailbx);
  340.             cp = dn_compress(cp,rrp->rdata.minfo.emailbx);
  341.         case TYPE_MD:        /* Unsupported type */
  342.         case TYPE_MF:        /* Unsupported type */
  343.         case TYPE_NULL:        /* Unsupported type */
  344.         case TYPE_WKS:        /* Unsupported type */
  345.             cp = dn_compress(cp,rrp->rdata.data);
  346.             break;
  347.         case TYPE_TXT:
  348.         default:
  349.             cp = put16(cp,rrp->rdlength);
  350.  
  351.             for(i=0 ; i < rrp->rdlength ; i++) {
  352.                 *cp++ = rrp->rdata.data[i];
  353.             }
  354.             break;
  355.         }
  356.     }
  357.     return cp;
  358. }
  359.  
  360. /* analyse suffixes for names to be added to the memory list */
  361. /* if Lorigin is empty, PA0GRI's domain stuf is not active.  */
  362. static void near
  363. analsuf(struct rr *rrp)
  364. {
  365.     struct dlist *llist, *lorigin;
  366.  
  367.     if(rrp->origin != NULLCHAR) {
  368.         /* no job for me. */
  369.         return;
  370.     }
  371.     if((llist = Lorigin) != NULLDLIST) {         /* Am i working for PA0GRI? */
  372.         int i = strlen(rrp->name);
  373.  
  374.         if(rrp->name[i-1] == '.') {
  375.             char *n1 = &rrp->name[i-1];
  376.             char *n2 = strchr(rrp->name,'.');
  377.  
  378.             if(n1 == n2) {
  379.                 return; /* only 1 dot */
  380.             }
  381.             n2++;   /* point byond dot */
  382.  
  383.             while(llist != NULLDLIST) {
  384.                 lorigin = llist;
  385.                 if(strcmp(llist->name,n2) == 0) {
  386.                     break;
  387.                 }
  388.                 llist = llist->next;
  389.             }
  390.             if(llist == NULLDLIST) {
  391.                 llist = mxallocw(sizeof(struct dlist));
  392.                 llist->name = strxdup(n2);
  393.                 lorigin->next = llist;
  394.             }
  395.             rrp->origin = llist->name;
  396.             n2--;
  397.             *n2 = '\0'; /* dot to EOS */
  398.             n1 = strxdup(rrp->name);
  399.             xfree(rrp->name);
  400.             rrp->name = n1;
  401.         }
  402.     }
  403. }
  404.  
  405. /* test a rr against a given name and type. The name can be:
  406.  1 a fully qualified name    (EG: pa0gri.ampr.org.)
  407.     or (if not fully qualified)
  408.  2 a name without a dot and no origin and suffix
  409.  3 a name without a dot and an origin and no suffix
  410.  4 a name without a dot and an origin and a suffix
  411.  *
  412.  * return 0 if not comparable, case value if it is good
  413.  */
  414. static int near
  415. dfind_cmp(struct rr *rrp,char *name,int nlen,int dlen)
  416. {
  417.     int olen = 0, rlen = strlen(rrp->name);
  418.  
  419.     if(rrp->origin != NULLCHAR) {
  420.         olen = strlen(rrp->origin);
  421.         if(rrp->origin[olen - 1] == '.')
  422.             --olen;
  423.     }
  424.  
  425. /* 1st test: is the name equal to the fully qualified rrp name? (minus traling .) */
  426.     if(rrp->name[rlen - 1] == '.') {
  427.         --rlen;
  428.         if(rlen == nlen && strnicmp(name,rrp->name,rlen) == 0)
  429.             return 1;
  430.     }
  431.  
  432. /* second test: is the name equal to the rrp name */
  433.     if(Dsuffix == NULLCHAR && rrp->origin == NULLCHAR) {
  434.         if(nlen == rlen && strnicmp(name,rrp->name,rlen) == 0)
  435.             return 2;
  436.         if(nlen + 9 == rlen             /* special case for .ampr.org. */
  437.          && strnicmp(name,rrp->name,nlen) == 0
  438.          && strnicmp(&rrp->name[nlen+1],"ampr.org",8) == 0
  439.          && rrp->name[nlen] == '.')
  440.             return 3;
  441.     } else if(Dsuffix == NULLCHAR && rrp->origin != NULLCHAR) {
  442.         if(nlen == rlen && strnicmp(name,rrp->name,rlen) == 0)
  443. /* third test: name equal to rrp name (excluding origin) */
  444.             return 4;
  445.         else if((rlen + olen + 1) == nlen
  446.              && strnicmp(name,rrp->name,rlen) == 0
  447.              && name[rlen] == '.'
  448.              && strnicmp(&name[rlen + 1],rrp->origin,olen) == 0)
  449. /* fourth test: name equal rrp name + origin */
  450.                 return 5;
  451.     } else if(Dsuffix != NULLCHAR && rrp->origin != NULLCHAR) {
  452.         if(rlen == nlen && dlen == olen
  453.          && strnicmp(name,rrp->name,rlen) == 0
  454.          && strnicmp(Dsuffix,rrp->origin,dlen) == 0)
  455. /* fifth test: name equal to rrp name and origin equal to domain suffix */
  456.             return 6;
  457.         else if((rlen + olen + 1) == nlen
  458.              && strnicmp(name,rrp->name,rlen) == 0
  459.              && name[rlen] == '.'
  460.              && strnicmp(&name[rlen + 1],rrp->origin,olen) == 0)
  461. /* sixth test: name equal to rrp name + origin) */
  462.                 return 7;
  463.     } else if(Dsuffix != NULLCHAR && rrp->origin == NULLCHAR) {
  464.         if(rlen == nlen && strnicmp(name,rrp->name,rlen) == 0)
  465. /* seventh test: name equal to rrp name and no origin (ignore domain suffix) */
  466.             return 8;
  467.         else
  468.             if((nlen + dlen + 1) == rlen
  469.              && strnicmp(name,rrp->name,nlen) == 0
  470.              && rrp->name[nlen] == '.'
  471.              && strnicmp(&rrp->name[nlen + 1],Dsuffix,dlen) == 0)
  472. /* eight test: name plus suffix equal to rrp name ) */
  473.                 return 9;
  474.     }
  475.     return 0;
  476. }
  477.  
  478. /* Search local domain file for resource record of specified name and type.
  479.  * If records were found, the domain file pointer is left just after the last
  480.  * one. If not, the file is rewound.
  481.  */
  482. static struct rr * near
  483. dfindf(FILE *dbase,char *name,int type,struct rr_memory *memory)
  484. {
  485.     struct rr *rrp;
  486.     int nlen = strlen(name);
  487.     int dlen = (Dsuffix != NULLCHAR) ? (strlen(Dsuffix) - 1) : 0;
  488.  
  489.     if(DBloaded) {
  490.         return NULLRR;
  491.     }
  492.     if(name[nlen - 1] == '.') {         /* forget trailing . for tests. */
  493.         --nlen;
  494.     }
  495.     /* Search file */
  496.     while((rrp = get_rr(dbase,memory)) != NULLRR) {
  497.         if(rrp->class == CLASS_IN) {
  498.             if(type == rrp->type || type == TYPE_ANY) {
  499.                 if(dfind_cmp(rrp,name,nlen,dlen) != 0) {
  500.                     break;
  501.                 }
  502.             }
  503.         }
  504.         free_rr(rrp);
  505.         pwait(NULL);    /* Give up CPU for a while, this takes time */
  506.     }
  507.     if(rrp == NULLRR) {
  508.         rewind(dbase);
  509.     }
  510.     return rrp;
  511. }
  512. #ifdef forgetme
  513.         /* If the first character is a '*' it is replaced by the
  514.            first part of the sought domain. */
  515. /* forget about this till other areas know what to do with multiple rr's.
  516.         if(*rrp->name == '*'){
  517.             if(rrp->name[rlen-1] == '.')
  518.                 p = mxallocw(rlen);
  519.             else
  520.                 p = mxallocw(rlen + olen);
  521.             strcpy(p,rrp->name+2);
  522.             if(rrp->name[rlen-1] != '.' && rrp->origin != NULLCHAR)
  523.                 strcat(p,rrp->origin);
  524.             rrp->origin = p;
  525.             olen = strlen(rrp->origin);
  526.             if(rrp->origin[olen-1] == '.')
  527.                 --olen;
  528.             xfree(rrp->name);
  529.             rrp->name = mxallocw(nlen + 1);
  530.             if(nlen > olen
  531.              && strnicmp(name+nlen-olen,rrp->origin, olen) == 0)
  532.                 strncpy(rrp->name,name,nlen-olen-1);
  533.             else {
  534.                 free_rr(rrp);
  535.                 continue;
  536.             }
  537.             rlen = strlen(rrp->name);
  538.         }
  539. end of skip code */
  540. #endif
  541.  
  542. struct rr *
  543. dfind(FILE *dbase,char *name,int type,struct rr_memory *memory)
  544. {
  545.     struct rr *rrp, *rrl;
  546.     int nlen, i, rtype;
  547.     int dlen = (Dsuffix != NULLCHAR) ? (strlen(Dsuffix) - 1) : 0;
  548.  
  549.     struct rr *rrsave = NULLRR;
  550.  
  551.     if(type >= NDTYPES) {
  552.         if(type == TYPE_ANY) {
  553.             for(i = 0 ; (rtype = Dstypes[i]) != 0; ) {
  554.                 rrp = dfind(dbase,name,rtype,memory);
  555.  
  556.                 if(rrp != NULLRR) {
  557.                     if(rrsave == NULLRR){
  558.                         rrsave = rrp;
  559.                         rrl = rrp;
  560.                     } else {
  561.                         rrl->next = rrp;
  562.                         rrl = rrl->next;
  563.                     }
  564.                 } else {
  565.                     i++;
  566.                     memory->rrp = NULLRR;
  567.                 }
  568.             }
  569.             if(rrsave != NULLRR) {
  570.                 return rrsave;
  571.             }
  572.         } else {
  573.             /* to big a type for memory */
  574.             goto filetest;
  575.         }
  576.     }
  577.     if((rrp = Rrlist[type]) != NULLRR) {
  578.         if(memory->rrp != NULLRR) {
  579.             rrp = memory->rrp; /* go off where we left before ! */
  580.             rrp = rrp->next; /* but take the next */
  581.         }
  582.         nlen = strlen(name);
  583.  
  584.         if(name[nlen - 1] == '.') {         /* forget trailing . for tests. */
  585.             --nlen;
  586.         }
  587.         /* Search core data beast */
  588.         while(rrp != NULLRR) {
  589.             if(rrp->class == CLASS_IN) {
  590.                 if(dfind_cmp(rrp,name,nlen,dlen) != 0) {
  591.                         break;
  592.                 }
  593.             }
  594.             rrp = rrp->next;
  595.         }
  596.         if(rrp != NULLRR){
  597.             rrl = copy_rr(rrp);
  598.             memory->rrp = rrp;
  599.             return rrl;
  600.         }
  601.         memory->rrp = NULLRR; /* end of list encountered */
  602.     }         /* not found in memory, resort to file */
  603. filetest:
  604.     if(dbase != NULLFILE) {
  605.         rrp = dfindf(dbase,name,type,memory);
  606.     }
  607.     return rrp;
  608. }
  609.  
  610. /* Add a record to the database only if it doesn't already exist */
  611. /* Return 1 if record is not added to memory list. This means the rr
  612.    can be freed. If 0 is returned the rr is added to the memory list */
  613. #ifndef ENH
  614. static
  615. #endif
  616. int
  617. add_rr(FILE *fp,struct rr *rrp1)
  618. {
  619.     int type, nlen;
  620.     char *name;
  621.     struct rr *rrp, *rr;
  622.     struct rr_memory *memory = mxallocw(sizeof(struct rr_memory));
  623.  
  624.     memory->rrp = NULLRR;
  625.  
  626.     analsuf(rrp1);
  627.  
  628.     type = rrp1->type;
  629.     name = rrp1->name;
  630.     nlen = strlen(name);
  631.  
  632.     if(fp == NULLFILE) {
  633.         name = strxdup(rrp1->name);
  634.         while((rrp = dfind(fp,name,type,memory)) != NULLRR) {
  635.             if(cmp_rr(rrp,rrp1) == 0) {
  636.                 free_rr(rrp);
  637.                 xfree(memory->dorigin);
  638.                 xfree(memory);
  639.                 xfree(name);
  640.                 return 1;
  641.             }
  642.             free_rr(rrp);
  643.         }
  644.         /* Not found in list, go add it */
  645.         xfree(memory->dorigin);
  646.         xfree(memory);
  647.         xfree(name);
  648.  
  649.         /* see if we have this kind of records. */
  650.         if((rr = Rrlist[type]) != NULLRR) {
  651.             rr = Rrlistl[type];
  652.             rr->next = rrp1;
  653.         } else {                         /* No, initialize first */
  654.             Rrlist[rrp1->type] = rrp1;
  655.         }
  656.         /* now set last */
  657.         Rrlistl[type] = rrp1;
  658.         return 0;
  659.     } else {
  660.         if(name[nlen - 1] != '.') {
  661.             if(rrp1->origin != NULLCHAR){
  662.                 name = mxallocw(nlen + strlen(rrp1->origin) + 2);
  663.                 sprintf(name,"%s.%s",rrp1->name,rrp1->origin);
  664.             }
  665.         } else {
  666.             name = strxdup(rrp1->name);
  667.         }
  668.         rewind(fp);
  669.  
  670.         while((rrp = dfind(fp,name,type,memory)) != NULLRR) {
  671.             if(cmp_rr(rrp,rrp1) == 0) {
  672.                 free_rr(rrp);
  673.                 xfree(memory->dorigin);
  674.                 xfree(memory);
  675.                 xfree(name);
  676.                 return 1;
  677.             }
  678.             free_rr(rrp);
  679.         }
  680.         xfree(memory->dorigin);
  681.         xfree(memory);
  682.         xfree(name);
  683.         fseek(fp,0,SEEK_END);
  684.         put_rr(fp,rrp1,1);
  685.         return 1;
  686.     }
  687. }
  688.  
  689. /* Compare two resource records, returning 0 if equal, nonzero otherwise */
  690. static int
  691. cmp_rr(struct rr *rr1,struct rr *rr2)
  692. {
  693.     int i;
  694.  
  695.     if(rr1 == NULLRR || rr2 == NULLRR) {
  696.         return -1;
  697.     }
  698.     if((i = strlen(rr1->name)) != strlen(rr2->name)) {
  699.         return 1;
  700.     }
  701.     if((i = strnicmp(rr1->name,rr2->name,i)) != 0) {
  702.         return i;
  703.     }
  704.     if(rr1->type != rr2->type) {
  705.         return 2;
  706.     }
  707.     if(rr1->class != rr2->class) {
  708.         return 3;
  709.     }
  710.     if(rr1->rdlength == 0 && rr2->rdlength == 0) {
  711.         return 0;
  712.     }
  713.     if(rr1->rdlength == 0 || rr2->rdlength == 0) {
  714.         return 4;
  715.     }
  716.     /* Note: rdlengths are not compared because they vary depending
  717.      * on the representation (ASCII or encoded) this record was
  718.      * generated from.
  719.      */
  720.     switch(rr1->type){
  721.     case TYPE_A:
  722.         i = rr1->rdata.addr != rr2->rdata.addr;
  723.         break;
  724.     case TYPE_SOA:
  725.         i = rr1->rdata.soa->serial != rr2->rdata.soa->serial;
  726.         break;
  727.     case TYPE_HINFO:
  728.         i = strcmp(rr1->rdata.hinfo.cpu,rr2->rdata.hinfo.cpu) ||
  729.             strcmp(rr1->rdata.hinfo.os,rr2->rdata.hinfo.os);
  730.         break;
  731.     case TYPE_MX:
  732.         i = strcmp(rr1->rdata.mx.exch,rr2->rdata.mx.exch);
  733.         break;
  734.     case TYPE_MINFO:    /* Unsupported type */
  735.         i = strcmp(rr1->rdata.minfo.rmailbx,rr2->rdata.minfo.rmailbx) ||
  736.             strcmp(rr1->rdata.minfo.emailbx,rr2->rdata.minfo.emailbx);
  737.         break;
  738.     case TYPE_MB:
  739.     case TYPE_MG:
  740.     case TYPE_MR:
  741.     case TYPE_PTR:
  742.     case TYPE_TXT:
  743.     case TYPE_NS:
  744.     case TYPE_CNAME:
  745. /*
  746.         i = strcmp(rr1->rdata.data,rr2->rdata.data);
  747.         break;
  748. */
  749.     case TYPE_MD:        /* Unsupported type */
  750.     case TYPE_MF:        /* Unsupported type */
  751.     case TYPE_NULL:        /* Unsupported type */
  752.     case TYPE_WKS:        /* Unsupported type */
  753.         i = strcmp(rr1->rdata.data,rr2->rdata.data);
  754.         break;
  755.     }
  756.     return i;
  757. }
  758.  
  759. struct rr *
  760. copy_rr(struct rr *rr)
  761. {
  762.     struct rr *rrp = mxallocw(sizeof(struct rr));
  763.  
  764.     rrp->next = NULLRR;
  765.     rrp->soarec = rr->soarec;
  766.     rrp->name = strxdup(rr->name);
  767.     rrp->type = rr->type;
  768.     rrp->class = rr->class;
  769.     rrp->ttl = rr->ttl;
  770.     rrp->origin = rr->origin;
  771.     rrp->rdlength = rr->rdlength;
  772.  
  773.     switch(rr->type){
  774.     case TYPE_A:
  775.         rrp->rdata.addr = rr->rdata.addr;
  776.         break;
  777.     case TYPE_HINFO:
  778.         rrp->rdata.hinfo.cpu = strxdup(rr->rdata.hinfo.cpu);
  779.         rrp->rdata.hinfo.os = strxdup(rr->rdata.hinfo.os);
  780.         break;
  781.     case TYPE_MX:
  782.         rrp->rdata.mx.pref = rr->rdata.mx.pref;
  783.         rrp->rdata.mx.exch = strxdup(rr->rdata.mx.exch);
  784.         break;
  785.     case TYPE_SOA:
  786.         rrp->rdata.soa = mxallocw(sizeof(struct soa));
  787.         rrp->rdata.soa->mname = strxdup(rr->rdata.soa->mname);
  788.         rrp->rdata.soa->rname = strxdup(rr->rdata.soa->rname);
  789.         rrp->rdata.soa->serial = rr->rdata.soa->serial;
  790.         rrp->rdata.soa->refresh = rr->rdata.soa->refresh;
  791.         rrp->rdata.soa->retry = rr->rdata.soa->retry;
  792.         rrp->rdata.soa->expire = rr->rdata.soa->expire;
  793.         rrp->rdata.soa->minimum = rr->rdata.soa->minimum;
  794.         break;
  795.     case TYPE_MINFO:    /* Unsupported type */
  796.         rrp->rdata.minfo.rmailbx = strxdup(rr->rdata.minfo.rmailbx);
  797.         rrp->rdata.minfo.emailbx = strxdup(rr->rdata.minfo.emailbx);
  798.         break;
  799.     case TYPE_CNAME:
  800.     case TYPE_MB:
  801.     case TYPE_MG:
  802.     case TYPE_MR:
  803.     case TYPE_NS:
  804.     case TYPE_PTR:
  805.     case TYPE_TXT:
  806. /*
  807.         rrp->rdata.name = strxdup(rr->rdata.name);
  808.         break;
  809. */
  810.     case TYPE_MD:        /* Unsupported type */
  811.     case TYPE_MF:        /* Unsupported type */
  812.     case TYPE_NULL:        /* Unsupported type */
  813.     case TYPE_WKS:        /* Unsupported type */
  814.         rrp->rdata.name = strxdup(rr->rdata.name);
  815.         break;
  816.     }
  817.     return rrp;
  818. }
  819.  
  820. #ifdef XXX
  821. struct rr *
  822. make_rr(int source,char *dname,int16 dclass,int16 dtype,int32 ttl,int16 rdl,void *data)
  823. {
  824.     struct rr *newrr = mxallocw(sizeof(struct rr));
  825.  
  826.     newrr->next = NULLRR;
  827.     newrr->soarec = NULLRR;
  828.     newrr->name = strxdup(dname);
  829.     newrr->class = dclass;
  830.     newrr->type = dtype;
  831.     newrr->ttl = ttl;
  832.  
  833.     if((newrr->rdlength = rdl) == 0) {
  834.         return newrr;
  835.     }
  836.     if(dtype == TYPE_A) {
  837.         int32 *ap = (int32 *)data;
  838.         newrr->rdata.addr = *ap;
  839.     }
  840.     return copy_rr(newrr);
  841. }
  842. #endif
  843.  
  844. /* Free a chain of resource records */
  845. void
  846. free_rr(struct rr *rrp)
  847. {
  848.     struct rr *rr = rrp;
  849.  
  850.     while(rr != NULLRR) {
  851.         rrp = rr;
  852.         xfree(rrp->name);
  853.  
  854.         if(rrp->rdlength != 0){
  855.             switch(rrp->type){
  856.             case TYPE_CNAME:
  857.             case TYPE_MB:
  858.             case TYPE_MG:
  859.             case TYPE_MR:
  860.             case TYPE_NS:
  861.             case TYPE_PTR:
  862.                 xfree(rrp->rdata.name);
  863.                 break;
  864.             case TYPE_A:
  865.                 break;    /* Nothing allocated in rdata section */
  866.             case TYPE_HINFO:
  867.                 xfree(rrp->rdata.hinfo.cpu);
  868.                 xfree(rrp->rdata.hinfo.os);
  869.                 break;
  870.             case TYPE_MX:
  871.                 xfree(rrp->rdata.mx.exch);
  872.                 break;
  873.             case TYPE_SOA:
  874.                 xfree(rrp->rdata.soa->mname);
  875.                 xfree(rrp->rdata.soa->rname);
  876.                 xfree(rrp->rdata.soa);
  877.                 break;
  878.             case TYPE_TXT:
  879.                 xfree(rrp->rdata.data);
  880.                 break;
  881.             case TYPE_MD:        /* Unsupported type */
  882.             case TYPE_MF:        /* Unsupported type */
  883.             case TYPE_NULL:        /* Unsupported type */
  884.                 xfree(rrp->rdata.data);
  885.                 break;
  886.             case TYPE_WKS:        /* Unsupported type */
  887.                 break;
  888.             case TYPE_MINFO:    /* Unsupported type */
  889.                 xfree(rrp->rdata.minfo.rmailbx);
  890.                 xfree(rrp->rdata.minfo.emailbx);
  891.                 break;
  892.             }
  893.         }
  894.         rr = rrp->next;
  895.         xfree(rrp);
  896.     }
  897. }
  898.  
  899. #define        LEN        128
  900.  
  901. #ifndef ENH
  902. static
  903. #endif
  904. struct rr *
  905. get_rr(FILE *fp,struct rr_memory *memory)
  906. {
  907.     char line[LEN], contline[LEN];
  908.     struct rr *rrp;
  909.     struct dlist *lorigin,*ltemp;
  910.     char *name, *ttl, *class, *type, *data;
  911.     int i;
  912.     int32 value;
  913.     static char delim[] = " \t\r\n";
  914.  
  915.     if(fp == NULLFILE) {
  916.         return NULLRR;
  917.     }
  918.     /* Search file */
  919.     while(fgets(line,LEN,fp) != NULL) {
  920.         if(*line == '#' || *line == ';') {
  921.             continue;
  922.         }
  923.         if(*line == '$') {
  924.             data = strtok(line,delim);
  925.  
  926.             if(strnicmp(data,"$origin",7) == 0) {
  927.                 data = strtok(NULLCHAR,delim);
  928.  
  929.                 if(Db_initialize) {
  930.                     if(data != NULLCHAR) {
  931.                         ltemp = Lorigin;
  932.  
  933.                         while(ltemp != NULLDLIST) {
  934.                             lorigin = ltemp;
  935.  
  936.                             if(strcmp(ltemp->name,data) == 0) {
  937.                                 break;
  938.                             }
  939.                             ltemp = ltemp->next;
  940.                         }
  941.                         if(ltemp == NULLDLIST) {
  942.                             ltemp = mxallocw(sizeof(struct dlist));
  943.                             ltemp->name = strxdup(data);
  944.                             lorigin->next = ltemp;
  945.                             Dorigin = ltemp->name;
  946.                         } else {
  947.                             Dorigin = ltemp->name;
  948.                         }
  949.                     } else {
  950.                         Dorigin = NULLCHAR; /* empty origin */
  951.                     }
  952.                 }
  953.                 if(memory->dorigin != NULLCHAR) {
  954.                     xfree(memory->dorigin);
  955.                 }
  956.                 memory->dorigin = (data != NULLCHAR) ? strxdup(data) : NULLCHAR;
  957.             }
  958.             continue;
  959.         }
  960.         data = &line[0];    /* check for empty line */
  961.  
  962.         while(*data)
  963.             if(!isspace(*data++)) {
  964.                 break;
  965.             }
  966.         /*
  967.          * now it is nor a # , ; or $ line
  968.          */
  969.         if(*data) {
  970.             break;    /* there is something on it.. */
  971.         }
  972.     }
  973.     if(feof(fp)) {
  974.         return NULLRR;
  975.     }
  976.     rrp = mxallocw(sizeof(struct rr));
  977.  
  978.     if(isspace(line[0])) {    /* in case of previous name usage*/
  979.         name = "";
  980.         ttl = strtok(line,delim);
  981.     } else {
  982.         name = strtok(line,delim);
  983.  
  984.         if(*name == '@' && (memory->dorigin != NULLCHAR
  985.           || Dsuffix != NULLCHAR)){
  986.             name = (memory->dorigin != NULLCHAR) ? memory->dorigin : Dsuffix;
  987.         }
  988.         ttl = strtok(NULLCHAR,delim);
  989.     }
  990.     if(ttl == NULLCHAR) {     /* If a line only contains a name */
  991.         goto badline;
  992.     }
  993.     if((i = strlen(name)) == 0) {
  994.         name = memory->Dname;
  995.     } else {
  996.         sprintf(memory->Dname,"%.125s",name);
  997.     }
  998.     rrp->origin = (Dorigin != NULLCHAR) ? Dorigin : memory->dorigin;
  999.  
  1000.     if(name[i-1] == '.') {        /* if a fully qualified name comes along */
  1001.         rrp->origin = NULLCHAR;    /* then it does not belong to an origin */
  1002.     }
  1003.     rrp->name = strxdup(name);
  1004.  
  1005.     if(!isdigit(ttl[0])) {
  1006.         /* Optional ttl field is missing; slide field over */
  1007.         class = ttl;
  1008.         ttl = NULLCHAR;
  1009.         rrp->ttl = memory->Dttl;
  1010.     } else {
  1011.         memory->Dttl = atol(ttl);
  1012.         rrp->ttl = memory->Dttl;
  1013.         class = strtok(NULLCHAR,delim);
  1014.     }
  1015.     if(class == NULLCHAR) {         /* If a line only contains a name and ttl */
  1016.         goto badline;
  1017.     }
  1018.     if(strcmp(class,"IN") != 0){
  1019.         /* Optional class field is missing; slide field over */
  1020.         type = class;
  1021.         class = NULLCHAR;
  1022.         rrp->class = memory->Dclass;
  1023.     } else {
  1024.         memory->Dclass = CLASS_IN;
  1025.         rrp->class = memory->Dclass;
  1026.         type = strtok(NULLCHAR,delim);
  1027.     }
  1028.     if(type == NULLCHAR) {    /* If a class field is missing */
  1029. badline:
  1030.         tprintf("Error in domain file %s:\n-%s-\n",Dfile,line);
  1031.         free_rr(rrp);
  1032.         return NULLRR;
  1033.     }
  1034.     for(i = 0; i < NRLIST; i++) {
  1035.         if(strcmp(type,type2str(i)) == 0) {
  1036.             rrp->type = i;
  1037.             break;
  1038.         }
  1039.     }
  1040.     data = strtok(NULLCHAR,delim);
  1041.  
  1042.     if(data == NULLCHAR) {
  1043.         return rrp;
  1044.     }
  1045.     switch(rrp->type){
  1046.     case TYPE_MD:        /* Unsupported yet */
  1047.     case TYPE_MF:        /* Unsupported yet */
  1048.     case TYPE_NULL:        /* Unsupported yet */
  1049. /*
  1050.         rrp->rdlength = strlen(data) + 1;
  1051.         rrp->rdata.name = strxdup(data);
  1052.         break;
  1053. */
  1054.     case TYPE_WKS:        /* Unsupported yet */
  1055. /*
  1056.         rrp->wks = mxallocw(sizeof(struct wks));
  1057.  */
  1058.     case TYPE_CNAME:
  1059.     case TYPE_MB:
  1060.     case TYPE_MG:
  1061.     case TYPE_MR:
  1062.     case TYPE_NS:
  1063.     case TYPE_PTR:
  1064.     case TYPE_TXT:
  1065.         rrp->rdlength = strlen(data) + 1;
  1066.         rrp->rdata.name = strxdup(data);
  1067.         break;
  1068.     case TYPE_A:
  1069.         rrp->rdlength = 4;
  1070.         rrp->rdata.addr = aton(data);
  1071.         break;
  1072.     case TYPE_HINFO:
  1073.         rrp->rdlength = strlen(data) + 2;
  1074.         rrp->rdata.hinfo.cpu = strxdup(data);
  1075.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1076.             rrp->rdlength += strlen(data);
  1077.             rrp->rdata.hinfo.os = strxdup(data);
  1078.         }
  1079.         break;
  1080.     case TYPE_MINFO:
  1081.         rrp->rdlength = strlen(data) + 2;
  1082.         rrp->rdata.minfo.rmailbx = strxdup(data);
  1083.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1084.             rrp->rdlength += strlen(data);
  1085.             rrp->rdata.minfo.emailbx = strxdup(data);
  1086.         }
  1087.         break;
  1088.     case TYPE_MX:
  1089.         rrp->rdata.mx.pref = atoi(data);
  1090.         rrp->rdlength = 2;
  1091.  
  1092.         /* Get domain name of exchanger */
  1093.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR) {
  1094.             rrp->rdlength += strlen(data) + 1;
  1095.             rrp->rdata.mx.exch = strxdup(data);
  1096.         }
  1097.         break;
  1098.     case TYPE_SOA:
  1099.         rrp->rdata.soa = mxallocw(sizeof(struct soa));
  1100.         /* Get domain name of master name server */
  1101.         rrp->rdlength = strlen(data) + 1;
  1102.         rrp->rdata.soa->mname = strxdup(data);
  1103.  
  1104.         /* Get domain name of irresponsible person */
  1105.         if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
  1106.             rrp->rdata.soa->rname = strxdup(data);
  1107.             rrp->rdlength += strlen(data) + 1;
  1108.         }
  1109.         data = strtok(NULLCHAR,delim);
  1110.  
  1111.         if(*data == '(') {    /* multiple line data */
  1112.             /* Search file */
  1113.             fgets(contline,LEN,fp);
  1114.             if(feof(fp)) {
  1115.                 break;
  1116.             }
  1117.             data = strtok(contline,delim);
  1118.  
  1119.             for(i = 0; i < 5; i++) {
  1120.                 if(*data == ';' || data == NULLCHAR) {
  1121.                     fgets(contline,LEN,fp);
  1122.                     if(feof(fp)) {
  1123.                         break;
  1124.                     }
  1125.                     data = strtok(contline,delim);
  1126.                 }
  1127.                 if(*data == ')') {
  1128.                     break;
  1129.                 }
  1130.                 if(isdigit(*data)) {
  1131.                     value = atol(data);
  1132.                     switch (i) {
  1133.                     case 0:
  1134.                         rrp->rdata.soa->serial = value;
  1135.                         break;
  1136.                     case 1:
  1137.                         rrp->rdata.soa->refresh = value;
  1138.                         break;
  1139.                     case 2:
  1140.                         rrp->rdata.soa->retry = value;
  1141.                         break;
  1142.                     case 3:
  1143.                         rrp->rdata.soa->expire = value;
  1144.                         break;
  1145.                     case 4:
  1146.                         rrp->rdata.soa->minimum = value;
  1147.                         break;
  1148.                     }
  1149.                 }
  1150.             data = strtok(NULLCHAR,delim);
  1151.             }
  1152.         } else {
  1153.             rrp->rdata.soa->serial = atol(data);
  1154.             data = strtok(NULLCHAR,delim);
  1155.             rrp->rdata.soa->refresh = atol(data);
  1156.             data = strtok(NULLCHAR,delim);
  1157.             rrp->rdata.soa->retry = atol(data);
  1158.             data = strtok(NULLCHAR,delim);
  1159.             rrp->rdata.soa->expire = atol(data);
  1160.             data = strtok(NULLCHAR,delim);
  1161.             rrp->rdata.soa->minimum = atol(data);
  1162.         }
  1163.         rrp->rdlength += 20;
  1164.         break;
  1165.     }
  1166.     return rrp;
  1167. }
  1168.  
  1169. /* Print a resource record */
  1170. #ifndef ENH
  1171. static
  1172. #endif
  1173. void
  1174. put_rr(FILE *fp,struct rr *rrp,int addorg)
  1175. {
  1176.     if(fp == NULLFILE || rrp == NULLRR) {
  1177.         return;
  1178.     }
  1179.     fputs(rrp->name,fp);
  1180.  
  1181.     if(addorg) {
  1182.         if(rrp->name[strlen(rrp->name)-1] != '.' && rrp->origin != NULLCHAR) {
  1183.             fprintf(fp,".%s",rrp->origin);
  1184.         }
  1185.     }
  1186.     if(rrp->ttl){
  1187.         fprintf(fp,"\t%lu",rrp->ttl);
  1188.     }
  1189.     if(rrp->class == CLASS_IN) {
  1190.         fputs("\tIN",fp);
  1191.     } else {
  1192.         if(rrp->ttl == 0) {
  1193.             fprintf(fp,"\t%lu",rrp->ttl);
  1194.         }
  1195.         fprintf(fp,"\t%u",rrp->class);
  1196.     }
  1197.     if(rrp->type < NDTYPES) {
  1198.         fprintf(fp,"\t%s",type2str(rrp->type));
  1199.     } else {
  1200.         fprintf(fp,"\t%u",rrp->type);
  1201.     }
  1202.     if(rrp->rdlength != 0) {
  1203.         fputc('\t',fp);
  1204.  
  1205.         switch(rrp->type){
  1206.         case TYPE_MINFO:    /* Unsupported type */
  1207.             fprintf(fp,"%s\t%s",rrp->rdata.minfo.rmailbx,rrp->rdata.minfo.emailbx);
  1208.             break;
  1209.         case TYPE_MD:        /* Unsupported type */
  1210.         case TYPE_MF:        /* Unsupported type */
  1211.         case TYPE_NULL:        /* Unsupported type */
  1212.         case TYPE_WKS:        /* Unsupported type */
  1213. /*
  1214.             fputs(rrp->rdata.data,fp);
  1215.             break;
  1216. */
  1217.         case TYPE_CNAME:
  1218.         case TYPE_MB:
  1219.         case TYPE_MG:
  1220.         case TYPE_MR:
  1221.         case TYPE_NS:
  1222.         case TYPE_PTR:
  1223.         case TYPE_TXT:
  1224.             /* These are all printable text strings */
  1225.             fputs(rrp->rdata.data,fp);
  1226.             break;
  1227.         case TYPE_A:
  1228.             fprintf(fp,"%s",inet_ntoa(rrp->rdata.addr));
  1229.             break;
  1230.         case TYPE_MX:
  1231.             fprintf(fp,"%u\t%s",rrp->rdata.mx.pref,rrp->rdata.mx.exch);
  1232.             break;
  1233.         case TYPE_SOA:
  1234.             fprintf(fp,"%s\t%s\t%lu\t%lu\t%lu\t%lu\t%lu",
  1235.                 rrp->rdata.soa->mname,
  1236.                 rrp->rdata.soa->rname,
  1237.                 rrp->rdata.soa->serial,
  1238.                 rrp->rdata.soa->refresh,
  1239.                 rrp->rdata.soa->retry,
  1240.                 rrp->rdata.soa->expire,
  1241.                 rrp->rdata.soa->minimum);
  1242.             break;
  1243.         case TYPE_HINFO:
  1244.             fprintf(fp,"%s\t%s",rrp->rdata.hinfo.cpu,rrp->rdata.hinfo.os);
  1245. /*
  1246.             break;
  1247. */
  1248.         default:
  1249.             break;
  1250.         }
  1251.     }
  1252.     fputc('\n',fp);
  1253.     fflush(fp);
  1254. }
  1255.  
  1256. /* Free a domain message */
  1257. void
  1258. free_dhdr(struct dhdr *dp)
  1259. {
  1260.     int i;
  1261.  
  1262.     if(dp->qdcount) {
  1263.         for(i = 0; i < dp->qdcount; i++) {
  1264.             xfree(dp->qlist[i]->qname);
  1265.             xfree(dp->qlist[i]);
  1266.         }
  1267.         xfree(dp->qlist);
  1268.     }
  1269.     if(dp->ancount) {
  1270.         for(i = 0; i < dp->ancount; i++) {
  1271.             free_rr(dp->ans[i]);
  1272.         }
  1273.         xfree(dp->ans);
  1274.     }
  1275.     if(dp->nscount) {
  1276.         for(i = 0; i < dp->nscount; i++) {
  1277.             free_rr(dp->ns[i]);
  1278.         }
  1279.         xfree(dp->ns);
  1280.     }
  1281.     if(dp->arcount) {
  1282.         for(i = 0; i < dp->arcount; i++) {
  1283.             free_rr(dp->add[i]);
  1284.         }
  1285.         xfree(dp->add);
  1286.     }
  1287.     xfree(dp);
  1288. }
  1289.  
  1290. int
  1291. ntohdomain(struct dhdr *dhdr,struct mbuf **bpp)
  1292. {
  1293.     int i;
  1294.  
  1295.     int16 tmp, len = len_p(*bpp);
  1296.     char *cp, *msg = mxallocw(len);
  1297.  
  1298.     memset(dhdr,0,sizeof(struct dhdr));
  1299.     pullup(bpp,msg,len);
  1300.     dhdr->id = get16(&msg[0]);
  1301.     tmp = get16(&msg[2]);
  1302.  
  1303.     if(tmp & DOM_RESPONSE) {
  1304.         dhdr->qr = 1;
  1305.     }
  1306.     dhdr->opcode = (tmp >> 11) & 0xf;
  1307.  
  1308.     if(tmp & DOM_AUTHORITY) {
  1309.         dhdr->aa = 1;
  1310.     }
  1311.     if(tmp & DOM_TRUNC) {
  1312.         dhdr->tc = 1;
  1313.     }
  1314.     if(tmp & DOM_DORECURSE) {
  1315.         dhdr->rd = 1;
  1316.     }
  1317.     if(tmp & DOM_CANRECURSE) {
  1318.         dhdr->ra = 1;
  1319.     }
  1320.     dhdr->rcode = tmp & 0xf;
  1321.     dhdr->qdcount = get16(&msg[4]);
  1322.     dhdr->ancount = get16(&msg[6]);
  1323.     dhdr->nscount = get16(&msg[8]);
  1324.     dhdr->arcount = get16(&msg[10]);
  1325.  
  1326.     /* Now parse the variable length sections */
  1327.     cp = &msg[12];
  1328.  
  1329.     /* Question section */
  1330.     if(dhdr->qdcount) {
  1331.         dhdr->qlist = cxallocw(dhdr->qdcount,sizeof(struct quest *));
  1332.     }
  1333.     for(i = 0; i < dhdr->qdcount; i++) {
  1334.         dhdr->qlist[i] = mxallocw(sizeof(struct quest));
  1335.  
  1336.         if((cp = getq(dhdr->qlist[i],msg,cp)) == NULLCHAR) {
  1337.             break;
  1338.         }
  1339.     }
  1340.     /* Answer section */
  1341.     if(dhdr->ancount) {
  1342.         dhdr->ans = cxallocw(dhdr->ancount,sizeof(struct rr *));
  1343.     }
  1344.     for(i = 0; i < dhdr->ancount; i++) {
  1345.         dhdr->ans[i] = mxallocw(sizeof(struct rr));
  1346.  
  1347.         if((cp = ntohrr(dhdr->ans[i],msg,cp)) == NULLCHAR) {
  1348.             break;
  1349.         }
  1350.     }
  1351.     /* Name server (authority) section */
  1352.     if(dhdr->nscount) {
  1353.         dhdr->ns = cxallocw(dhdr->nscount,sizeof(struct rr *));
  1354.     }
  1355.     for(i = 0; i < dhdr->nscount; i++) {
  1356.         dhdr->ns[i] = mxallocw(sizeof(struct rr));
  1357.  
  1358.         if((cp = ntohrr(dhdr->ns[i],msg,cp)) == NULLCHAR) {
  1359.             break;
  1360.         }
  1361.     }
  1362.     /* Additional section */
  1363.     if(dhdr->arcount) {
  1364.         dhdr->add = cxallocw(dhdr->arcount,sizeof(struct rr *));
  1365.     }
  1366.     for(i = 0; i < dhdr->arcount; i++) {
  1367.         dhdr->add[i] = mxallocw(sizeof(struct rr));
  1368.  
  1369.         if((cp = ntohrr(dhdr->add[i],msg,cp)) == NULLCHAR) {
  1370.             break;
  1371.         }
  1372.     }
  1373.     xfree(msg);
  1374.     return 0;
  1375. }
  1376.  
  1377. void
  1378. proc_answer(struct dhdr *dhdr,struct dserver *dp,FILE *dfp)
  1379. {
  1380.     FILE *fp;
  1381.     int i;
  1382.     long ttl = 500;        /* Default TTL for negative records without SOA */
  1383.     struct rr *rrp;
  1384.  
  1385.     /* Compute and update the round trip time if its a domain server */
  1386.     if(dp != NULLDOM) {
  1387.         int32 rtt = ((secclock() - (int32)dhdr->id)) * 1000;
  1388.         int32 abserr = rtt > dp->srtt ? rtt - dp->srtt : dp->srtt - rtt;
  1389.         dp->srtt = ((AGAIN-1) * dp->srtt + rtt + (AGAIN/2)) >> LAGAIN;
  1390.         dp->mdev = ((DGAIN-1) * dp->mdev + abserr + (DGAIN/2)) >> LDGAIN;
  1391.         dp->timeout = 4 * dp->mdev + dp->srtt;
  1392.     }
  1393.  
  1394.     if(DBloaded == 1 && dfp == NULLFILE) {
  1395.         fp = NULLFILE;                        /* append to memory */
  1396.     } else {
  1397.         if(dfp == NULLFILE) {
  1398.             if((fp = Fopen(Dfile,APPEND_TEXT,0,1)) == NULLFILE) {
  1399.                 return;
  1400.             }
  1401.         } else {
  1402.             fp = dfp;
  1403.         }
  1404.     }
  1405.     if(dhdr->aa && (dhdr->rcode == NAME_ERROR || dhdr->ancount == 0)) {
  1406.         /* Add negative reply to file. This assumes that there was
  1407.          * only one question, which is true for all questions we send.
  1408.          */
  1409.         struct quest *qp = dhdr->qlist[0];
  1410.         rrp = mxallocw(sizeof(struct rr));
  1411.  
  1412.         rrp->name = strxdup(qp->qname);
  1413.         rrp->type = qp->qtype;
  1414.         rrp->class = qp->qclass;
  1415.         rrp->ttl = ttl;
  1416.         rrp->rdlength = 0;    /* no data */
  1417.  
  1418.         if(rrp->type == TYPE_A) {
  1419.             if(add_rr(fp,rrp)) {
  1420.                 free_rr(rrp);            /* was already there */
  1421.             }
  1422.         }
  1423.     }
  1424.     if(dhdr->rcode == NO_ERROR) {
  1425.         for(i = 0; i < dhdr->ancount; i++) {
  1426.             rrp = copy_rr(dhdr->ans[i]);
  1427.  
  1428.             if(rrp->type == TYPE_SOA) {
  1429.                 ttl = rrp->ttl;
  1430.             }
  1431.             if(add_rr(fp,rrp)) {
  1432.                 free_rr(rrp);
  1433.             }
  1434.         }
  1435.         for(i = 0; i < dhdr->nscount; i++) {
  1436.             rrp = copy_rr(dhdr->ns[i]);
  1437.  
  1438.             if(rrp->type == TYPE_SOA) {
  1439.                 ttl = rrp->ttl;
  1440.             }
  1441.             if(add_rr(fp,rrp)) {
  1442.                 free_rr(rrp);
  1443.             }
  1444.         }
  1445.         for(i = 0; i < dhdr->arcount; i++) {
  1446.             rrp = copy_rr(dhdr->add[i]);
  1447.  
  1448.             if(rrp->type == TYPE_SOA) {
  1449.                 ttl = rrp->ttl;
  1450.             }
  1451.             if(add_rr(fp,rrp)) {
  1452.                 free_rr(rrp);
  1453.             }
  1454.         }
  1455.     }
  1456.     if(fp != NULLFILE && dfp == NULLFILE) {
  1457.         Fclose(fp);
  1458.     }
  1459. }
  1460.  
  1461. char *
  1462. type2str(int type)
  1463. {
  1464.     static char *Dtypes[] = {
  1465.         "Dt", "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG",
  1466.         "MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT"
  1467.     };
  1468.  
  1469.     if(type < NDTYPES) {
  1470.         return Dtypes[type];
  1471.     } else {
  1472.         switch (type) {
  1473.         case TYPE_AXFR:
  1474.             return "AXFR";
  1475.         case TYPE_MAILB:
  1476.             return "MAILB";
  1477.         case TYPE_MAILA:
  1478.             return "MAILA";
  1479.         case TYPE_ANY:
  1480.             return "ANY";
  1481.         }
  1482.     }
  1483.     return "UNKNOWN";
  1484. }
  1485.  
  1486. /* Return 1 if string appears to be an IP address in dotted decimal;
  1487.  * return 0 otherwise (i.e., if string is a domain name)
  1488.  */
  1489. int
  1490. isaddr(char *s)
  1491. {
  1492.     char c;
  1493.  
  1494.     if(s != NULLCHAR) {
  1495.         while((c = *s++) != '\0') {
  1496.             if(c != '[' && !isdigit(c) && c != '.') {
  1497.                 return 0;
  1498.             }
  1499.         }
  1500.     }
  1501.     return 1;
  1502. }
  1503.  
  1504. struct dhdr *
  1505. bld_dhdr(int16 qr,int16 op,int16 flags,int16 rcode,char *name,int class,int type)
  1506. {
  1507.     struct dhdr *dhdr = mxallocw(sizeof(struct dhdr));
  1508.  
  1509.     if(flags & DOM_AUTHORITY) {
  1510.         dhdr->aa = 1;
  1511.     }
  1512.     if(flags & DOM_TRUNC) {
  1513.         dhdr->tc = 1;
  1514.     }
  1515.     if(flags & DOM_DORECURSE) {
  1516.         dhdr->rd = 1;
  1517.     }
  1518.     if(flags & DOM_CANRECURSE) {
  1519.         dhdr->ra = 1;
  1520.     }
  1521.     dhdr->qr = qr;
  1522.     dhdr->opcode = op;
  1523.     dhdr->rcode = rcode;
  1524.     dhdr->id = (int16)secclock();
  1525.     dhdr->qdcount = 1;
  1526.     dhdr->qlist = cxallocw(dhdr->qdcount,sizeof(struct quest *));
  1527.     dhdr->qlist[0] = mxallocw(sizeof(struct quest));
  1528.     dhdr->qlist[0]->qname = strxdup(name);
  1529.     dhdr->qlist[0]->qtype = type;
  1530.     dhdr->qlist[0]->qclass = class;
  1531.     return dhdr;
  1532. }
  1533.  
  1534. int
  1535. res_mkbuf(struct dhdr *dhdr,char *buffer,int16 buflen)
  1536. {
  1537.     int16 parameter;
  1538.     int i, count;
  1539.     char *cp = buffer;
  1540.  
  1541.     cp = put16(cp,dhdr->id);
  1542.  
  1543.     parameter = (dhdr->qr) ? 0x8000 : 0;
  1544.     parameter |= ((dhdr->opcode & 0x0f) << 11);
  1545.  
  1546.     if(dhdr->aa) {
  1547.         parameter |= DOM_AUTHORITY;
  1548.     }
  1549.     if(dhdr->tc) {
  1550.         parameter |= DOM_TRUNC;
  1551.     }
  1552.     if(dhdr->rd) {
  1553.         parameter |= DOM_DORECURSE;
  1554.     }
  1555.     if(dhdr->ra) {
  1556.         parameter |= DOM_CANRECURSE;
  1557.     }
  1558.     parameter |= (dhdr->rcode & 0x0f);
  1559.  
  1560.     cp = put16(cp,parameter);
  1561.     cp = put16(cp,dhdr->qdcount);
  1562.     cp = put16(cp,dhdr->ancount);
  1563.     cp = put16(cp,dhdr->nscount);
  1564.     cp = put16(cp,dhdr->arcount);
  1565.  
  1566.     if((count = dhdr->qdcount) > 0) {
  1567.         for(i = 0; i < count; i++) {
  1568.             cp = dn_compress(cp,dhdr->qlist[i]->qname);
  1569.             cp = put16(cp,dhdr->qlist[i]->qtype);
  1570.             cp = put16(cp,dhdr->qlist[i]->qclass);
  1571.         }
  1572.     }
  1573.     if((count = dhdr->ancount) > 0) {
  1574.         for(i = 0; i < count; i++) {
  1575.             cp = htonrr(dhdr->ans[i],cp);
  1576.         }
  1577.     }
  1578.     if((count = dhdr->nscount) > 0) {
  1579.         for(i = 0; i < count; i++) {
  1580.             cp = htonrr(dhdr->ns[i],cp);
  1581.         }
  1582.     }
  1583.     if((count = dhdr->arcount) > 0) {
  1584.         for(i = 0; i < count; i++) {
  1585.             cp = htonrr(dhdr->add[i],cp);
  1586.         }
  1587.     }
  1588.     return (int)(cp - buffer);
  1589. }
  1590.  
  1591.